<?php

final class OOWP_Bootstrap
{

    private $dict = array( );

    private static $instance;

    private function __construct( )
    {
        $this->dict = array(
            'namespaces' => array( ),
        );
    }

    public function __clone( ) { }

    public static function get_instance( )
    {
        if (!isset(self::$instance)) {
            $class = __CLASS__;
            self::$instance = new $class;
        }
        return self::$instance;
    }

    /* ACCESSORS */

    public function __get($name)
    {
        $method = 'get' . OOWP_Base::convert_underscores($name);
        if (method_exists($this, $method)) {
            return $this->$method( );
        } else {
            throw new Exception("Cannot get attribute '$name'");
        }
    } // __get

    public function __set($name, $value)
    {
        $method = 'set' . OOWP_Base::convert_underscores($name);
        if (method_exists($this, $method)) {
            $this->$method($value);
        } else {
            throw new Exception("Cannot set attribute '$name'");
        }
    } // __set

    private function getNamespaces( )
    {
        if (isset($this->dict['namespaces'])) {
            return $this->dict['namespaces'];
        }
        return null;
    }

    private function getQuery( )
    {
        if (isset($this->dict['namespaces'])) {
            return $this->dict['query'];
        }
        return null;
    }

    private function setQuery(WP_Query $query)
    {
        $this->dict['query'] = $query;
    }

    /* METHODS */

    public function register_child_namespace($name)
    {
        if (!OOWP_Base::is_wellformed_string($name)) {
            throw new Exception("Expected wellformed string, got '$name'.");
        }
        if (!in_array($name, $this->namespaces)) {
            $this->dict['namespaces'][ ] = $name;
        }
    }

    public function register_query(WP_Query $query)
    {
        $this->dict['query'] = $query;
    }

    public function resolve_controller( )
    {
        $all_controllers = array( );
        $namespaces = $this->namespaces;

        foreach ($namespaces as $namespace) {
            $class = $namespace . '_Config';
            if (class_exists($class)) {
                $controllers = $class::get_controllers( );
                if (is_array($controllers)) {
                    foreach ($controllers as $controller) {
                        $all_controllers[ ] = $controller;
                    }
                }
            }
        }

        if (!$all_controllers) {
            throw new Exception('No controllers found');
        }

        $matching_controllers = array( );
        foreach ($all_controllers as $class) {
            if (class_exists($class)) {
                if ($class::matches($this->query)) {
                    $matching_controllers[ ] = $class;
                }
            }
        }

        if (!$matching_controllers) {
            echo OOWP_Bootstrap::format_query($this->query);
            throw new Exception("No matching controllers found!");
        } else {
            $class = $matching_controllers[0];

            $controller = new $class(array(
                'query' => $this->query
            ));

            return $controller;
        }
    }

    public static function format_query(WP_Query $query)
    {
        $result = '';
        $result .= '<pre>';
        ob_start();
        var_dump($query);
        $capture = ob_get_contents();
        ob_end_clean();
        $result .= htmlspecialchars($capture, ENT_QUOTES);
        $result .= '</pre>';
        return $result;
    }

}
